package com.qiangzi.workflow.engine.bpmn.flow;

import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;

import com.qiangzi.workflow.engine.bpmn.base.ProcessInstance;
import com.qiangzi.workflow.engine.bpmn.base.State;
import com.qiangzi.workflow.engine.bpmn.expression.ConditionExpression;

public class SequenceFlow extends Flow {

    public static final Logger  LOGGER = LoggerFactory.getLogger(SequenceFlow.class);

    // 条件表达式
    private ConditionExpression conditionExpression;

    public ConditionExpression getConditionExpression() {
        return conditionExpression;
    }

    public void parse(Element element) throws Exception {

        super.parse(element);

        Assert.isTrue(null != element, "element is null");

        // 条件表达式可选
        ConditionExpression conditionExpression = null;
        Element conditionElement = element.element("conditionExpression");
        if (null != conditionElement) {
            conditionExpression = new ConditionExpression();
            conditionExpression.parse(conditionElement);
        }
        this.conditionExpression = conditionExpression;

    }

    public Object copy() {
        SequenceFlow sequenceFlow = new SequenceFlow();
        copy(sequenceFlow);
        return sequenceFlow;
    }

    protected void copy(Object obj) {

        super.copy(obj);

        // 表达式直接引用就可以
        SequenceFlow sequenceFlow = (SequenceFlow) obj;
        sequenceFlow.conditionExpression = this.conditionExpression;

    }

    @Override
    public void invoke(ProcessInstance instance,
                       ApplicationContext applicationContext) throws Exception {

        // 根据条件表达式来
        if (null == this.conditionExpression) {
            setState(State.INVOKED);
            LOGGER.debug("edge [{}]-> {}", getId(), "invoked");
            return;
        }

        // 下面表示有表达式,则需要构造引擎来判断
        // 条件表达式实时计算比较好,因为事先并不知道哪些表达式会真正触发计算
        // https://www.jianshu.com/p/f1e76d4af5d8

        // 根据计算结果来设置自己的状态
        boolean result = instance.getExpressionValue(conditionExpression);
        setState(result ? State.INVOKED : State.IGNORED);
        LOGGER.debug("edge [{}] -> {}", getId(), result ? "invoked" : "ignored");

    }

}